package by.pavlyukevich.paymentsystem.panel;

import javax.inject.Inject;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.event.Broadcast;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.springframework.orm.jpa.JpaSystemException;

import by.pavlyukevich.paymentsystem.add.AbstractDataProvider;
import by.pavlyukevich.paymentsystem.add.AdminAjaxLink;
import by.pavlyukevich.paymentsystem.add.ErrorEvent;
import by.pavlyukevich.paymentsystem.add.PanelUpdateEvent;
import by.pavlyukevich.paymentsystem.add.UpdateEvent;
import by.pavlyukevich.paymentsystem.add.UserAjaxLink;
import by.pavlyukevich.paymentsystem.dataaccess.filter.AccountFilter;
import by.pavlyukevich.paymentsystem.dataaccess.filter.CardFilter;
import by.pavlyukevich.paymentsystem.dataaccess.filter.Filter;
import by.pavlyukevich.paymentsystem.datamodel.Account;
import by.pavlyukevich.paymentsystem.datamodel.Account_;
import by.pavlyukevich.paymentsystem.datamodel.user.UserAccount;
import by.pavlyukevich.paymentsystem.panel.card.CardListPanel;
import by.pavlyukevich.paymentsystem.panel.user.ContractorEditPanel;
import by.pavlyukevich.paymentsystem.panel.user.IndividualEditPanel;
import by.pavlyukevich.paymentsystem.services.AccountService;
import by.pavlyukevich.paymentsystem.webapp.BasicAuthenticationSession;

public class AccountListPanel extends Panel {

	@Inject
	private AccountService accountService;
	private AccountFilter accountFilter;
	private Panel respPanel;

	public AccountListPanel(String id) {
		this(id, new AccountFilter());
	}

	public AccountListPanel(String id, AccountFilter accountFilter) {
		super(id);
		this.accountFilter = accountFilter;
		this.respPanel = this;
	}

	@Override
	protected void onInitialize() {
		super.onInitialize();
		setOutputMarkupId(true);

		boolean isAdmin = BasicAuthenticationSession.get().getRoles().contains("ADMIN");

		AccountDataProvider accountDP = new AccountDataProvider(Account_.accountNumber,
				accountFilter);

		final WebMarkupContainer accountTable = new WebMarkupContainer("account-table");
		accountTable.setOutputMarkupId(true);
		add(accountTable);

		DataView<Account> dataView = new DataView<Account>("account-row", accountDP, 20) {

			@Override
			protected void populateItem(Item<Account> item) {

				final Account account = item.getModelObject();

				item.add(new Label("accountNumber"));
				item.add(new Label("balance"));
				item.add(new CheckBox("isBlocked").setEnabled(false));

				UserAccount userAccount = account.getUserAccount();

				String owner = (userAccount.getIndividual() == null) ? userAccount.getContractor()
						.getName() : userAccount.getIndividual().getFamily() + " "
						+ userAccount.getIndividual().getName();

				Panel ownerPanel = (userAccount.getIndividual() == null) ? new ContractorEditPanel(
						"ac-panel", userAccount.getContractor(), respPanel)
						: new IndividualEditPanel("ac-panel", userAccount.getIndividual(),
								respPanel);

				item.add(new AjaxLink<Void>("owner") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						send(getPage(), Broadcast.BREADTH, new PanelUpdateEvent(target, ownerPanel));
					}
				}.setBody(new Model<String>(owner)).setEnabled(isAdmin));

				item.add(new AdminAjaxLink<Void>("cards") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						send(getPage(), Broadcast.BREADTH,
								new PanelUpdateEvent(target, new CardListPanel("ac-panel",
										new CardFilter().setAccount(account))));
					}
				});

				item.add(new AdminAjaxLink<Void>("delete") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						try {
							accountService.delete(account);
							target.add(respPanel);
						} catch (JpaSystemException e) {
							error(new ResourceModel("t.error.unableToDelete").getObject());
							send(getPage(), Broadcast.BREADTH, new ErrorEvent(target));
						}
					}
				});

				item.add(new AdminAjaxLink<Void>("edit") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						send(getPage(), Broadcast.BREADTH, new PanelUpdateEvent(target,
								new AccountEditPanel("ac-panel", account, respPanel)));
					}
				});

				UserAjaxLink<Void> blockLink = new UserAjaxLink<Void>("block") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						account.setIsBlocked(!(account.getIsBlocked()));
						accountService.saveOrUpdate(account);
						send(getPage(), Broadcast.BREADTH, new UpdateEvent(target, account));
					}
				};
				item.add(blockLink);
				blockLink.setBody(new ResourceModel((account.getIsBlocked() == true) ? "b.unblock"
						: "b.block"));

			}

		};

		accountTable.add(dataView);
		add(new AdminAjaxLink<Void>("new") {

			@Override
			public void onClick(AjaxRequestTarget target) {
				Account account = new Account();
				account.setUserAccount(accountFilter.getUserAccount());
				send(getPage(), Broadcast.BREADTH, new PanelUpdateEvent(target,
						new AccountEditPanel("ac-panel", account, respPanel)));
			}
		});

		add(new MyPagingNavigator("paging", dataView));

		add(new OrderByBorder<SingularAttribute<Account, ?>>("sortByAccount",
				Account_.accountNumber, accountDP));
		add(new OrderByBorder<SingularAttribute<Account, ?>>("sortByBalance", Account_.balance,
				accountDP));

	}

	private class AccountDataProvider extends AbstractDataProvider<Account> {
		public AccountDataProvider(SingularAttribute<Account, ?> sortParam, Filter<Account> filter) {
			super(sortParam, filter, accountService);
		}
	};

}
